//
//  NumberButton.swift
//  ZZUI
//
//  Created by 张文晏 on 2018/11/8.
//  Copyright © 2018 张文晏. All rights reserved.
//  数量编辑按钮

import UIKit

@IBDesignable public class NumberButton: UIView {
    
    // MARK: - Subviews
    /// 数量输入框
    let textField = UITextField()
    /// 减号按钮
    let decreaseBtn = UIButton()
    /// 加号按钮
    let increaseBtn = UIButton()
    /// 快速加减定时器
    var timer: Timer?
    
    // MARK: - Variables
    /// 当输入改变时就调用数字改变回调闭包(默认当编辑结束时才调用)
    @IBInspectable public var editingChangedMode: Bool = true
    /// 最小值
    @IBInspectable public var minValue: Decimal = 0
    /// 最大值
    @IBInspectable public var maxValue: Decimal = 100000000
    /// 最多小数位
    @IBInspectable public var maximumFractionDigits = 6
    /// 当前数值
    public var currentNumber: Decimal {
        if let str = textField.text, let number = Decimal(string: str) {
            return number
        } else {
            return 0
        }
    }
    /// 数字改变回调
    public var numberChangedClosure: ((_ number: Decimal) -> Void)?
    
    
    // MARK: - View
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override public func awakeFromNib() {
        super.awakeFromNib()
        setupUI()
    }
    
    override public func layoutSubviews() {
        super.layoutSubviews()
        decreaseBtn.frame = CGRect(x: 0, y: 0, width: bounds.height, height: bounds.height)
        increaseBtn.frame = CGRect(
            x: bounds.width - bounds.height, y: 0, width: bounds.height, height: bounds.height
        )
        textField.frame = CGRect(
            x: bounds.height, y: 0, width: bounds.width - 2 * bounds.height, height: bounds.height
        )
    }
    
    // MARK: - Setup
    func setupUI() {
        layer.cornerRadius = 2
        backgroundColor = UIColor(hex: 0xf7f7f7)
        
        addSubview(textField)
        textField.textAlignment = .center
        textField.keyboardType = .decimalPad
        textField.font = UIFont.systemFont(ofSize: 16)
        textField.delegate = self
        textField.addTarget(self, action: #selector(textFieldTextDidChange), for: .editingChanged)
        
        setupBtn(sender: decreaseBtn)
        setupBtn(sender: increaseBtn)
    }
    
    @objc func textFieldTextDidChange() {
        guard editingChangedMode, let num = Decimal(string: textField.text ?? "") else { return }
        numberChangedClosure?(num)
    }
    
    func setupBtn(sender: UIButton) {
        addSubview(sender)
        sender.addTarget(self, action: #selector(touchDown(_:)), for: .touchDown)
        sender.addTarget(self, action: #selector(touchUp(_:)), for: .touchUpOutside)
        sender.addTarget(self, action: #selector(touchUp(_:)), for: .touchUpInside)
        sender.addTarget(self, action: #selector(touchUp(_:)), for: .touchCancel)
        if sender == decreaseBtn { // 减号按钮
            sender.setImage(NCUIBundle.image("ui_number_button_decrease_gray"), for: .normal)
            sender.setImage(NCUIBundle.image("ui_number_button_decrease_blue"), for: .highlighted)
        } else { // 加号按钮
            sender.setImage(NCUIBundle.image("ui_number_button_increase_gray"), for: .normal)
            sender.setImage(NCUIBundle.image("ui_number_button_increase_blue"), for: .highlighted)
        }
    }
    
    // MARK: - Action
    @objc func touchDown(_ btn: UIButton) {
        textField.endEditing(false)
        if btn == decreaseBtn {
            timer = Timer.scheduledTimer(
                timeInterval: 0.15,
                target: self,
                selector: #selector(decreaseAction),
                userInfo: nil,
                repeats: true
            )
        } else {
            timer = Timer.scheduledTimer(
                timeInterval: 0.15,
                target: self,
                selector: #selector(increaseAction),
                userInfo: nil,
                repeats: true
            )
        }
        timer?.fire()
    }
    
    @objc func touchUp(_ button: UIButton) {
        cleanTimer()
    }
    
    func cleanTimer() {
        if timer?.isValid != nil {
            timer?.invalidate()
            timer = nil
        }
    }
    
    @objc func decreaseAction() {
        guard let str = textField.text, let q = Decimal(string: str), q > minValue else { return }
        let num = max(q - 1, minValue)
        textField.text = "\(num)"
        numberChangedClosure?(num)
    }
    
    @objc func increaseAction() {
        var num: Decimal
        if let str = textField.text, let q = Decimal(string: str), q < maxValue {
            num = min(q + 1, maxValue)
        } else {
            num = min(minValue + 1, maxValue)
        }
        textField.text = "\(num)"
        numberChangedClosure?(num)
    }
    
}

extension NumberButton {
    
    public func setCurrentNumber(_ num: Decimal) {
        var str = String.init(describing: num)
        if str.hasPrefix(".") {
            str = "0" + str
        }
        textField.text = str
    }
    
}

extension NumberButton: UITextFieldDelegate {
    
    public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let text = textField.text else { return false }
        let newString = (text as NSString).replacingCharacters(in: range, with: string)
        let newNumber = Decimal(string: newString) ?? 0
        guard newNumber <= maxValue else { return false }
        if newString.isEmpty {
            return true
        } else {
            if let num = Decimal(string: newString) {
                if num > maxValue || num < minValue {
                    return false
                } else {
                    let expression = "^[0-9]*(\\.[0-9]{0,\(maximumFractionDigits)})?$"
                    guard let regex = try? NSRegularExpression(
                        pattern: expression,
                        options: .allowCommentsAndWhitespace
                        ) else {
                            return false
                    }
                    let numberOfMatches = regex.numberOfMatches(
                        in: newString,
                        options: .reportProgress,
                        range: NSMakeRange(0, newString.count)
                    )
                    return numberOfMatches != 0
                }
            } else {
                return false
            }
        }
    }
    
    public func textFieldDidEndEditing(_ textField: UITextField) {
        guard !editingChangedMode else { return }
        if let text = textField.text, !text.isEmpty, let num = Decimal(string: text) {
            textField.text = "\(num)"
            numberChangedClosure?(num)
        } else {
            textField.text = ""
            numberChangedClosure?(0)
        }
    }
    
}
